#region MIT Licence
/*
 * Copyright (C) 2014 PdfCreative
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom 
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included 
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace PdfCreative.Pdf.Graphics
{
    /// <summary>
    /// The Rectangle structure represents a rectangle, and is used by drawing operations of the Graphics class.
    /// </summary>
    public struct Rectangle
    {
        // Private fields
        // ==============
        #region Private fields
        private float _left;
        private float _top;
        private float _width;
        private float _height;
        #endregion



        // Public properties
        // =================
        #region Public properties
        /// <summary>
        /// Sets or retrieves the rectangle's left coordinate.
        /// </summary>
        public float Left
        {
            get { return _left; }
            set { _left = value; }
        }

        /// <summary>
        /// Sets or retrieves the rectangle's top coordinate.
        /// </summary>
        public float Top
        {
            get { return _top; }
            set { _top = value; }
        }

        /// <summary>
        /// Sets or retrieves the rectangle's width.
        /// </summary>
        public float Width
        {
            get { return _width; }
            set { _width = value; }
        }

        /// <summary>
        /// Sets or retrieves the rectangle's height.
        /// </summary>
        public float Height
        {
            get { return _height; }
            set { _height = value; }
        }

        /// <summary>
        /// Returns the right-most coordinate of the rectangle.
        /// </summary>
        public float Right
        {
            get { return _left + _width; }
        }

        /// <summary>
        /// Returns the top-most coordinate of the rectangle.
        /// </summary>
        public float Bottom
        {
            get { return _top + _height; }
        }

        /// <summary>
        /// Returns a value that represents an empty rectangle.
        /// </summary>
        public static Rectangle Empty
        {
            get { return new Rectangle(); }
        }
        #endregion



        // Public methods
        // ==============
        #region Public methods
        /// <summary>
        /// Returns a value that indicates if the reference is empty.
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return
                0 == _left && 0 == _top && 0 == _width && 0 == _height;
        }

        /// <summary>
        /// Moves the rectangle to the right, and upwards, by the amount specified.
        /// </summary>
        /// <param name="right">The amount to move the rectangle to the right.</param>
        /// <param name="down">The amount to move the rectangle down.</param>
        public void Move(float right, float down)
        {
            _left = _left + right;
            _top = _top + down;
        }

        /// <summary>
        /// Resizes the rectangle to the new width and height.
        /// </summary>
        /// <param name="width">The width</param>
        /// <param name="height">The height</param>
        public void Resize(float width, float height)
        {
            _width = width;
            _height = height;
        }

        /// <summary>
        /// Scales the rectangle by the specified X and Y scale. Scaling a Rectangle
        /// scales its position as well as its size.
        /// </summary>
        /// <param name="xscale">The horizontal scaling factor</param>
        /// <param name="yscale">The vertical scaling factor</param>
        public void Scale(float xscale, float yscale)
        {
            _left *= xscale;
            _top *= yscale;
            _width *= xscale;
            _height *= yscale;
        }

        /// <summary>
        /// Expands the rectangle by the specified offsets. The rectangle will expand in either direction
        /// on the axes that expand, in equal parts. So, expanding its width by 10 means that it will move 5 to the
        /// left and increase its width by 10 so that it's right-most coordinate is 5 further than originally.
        /// The width and height can be negative values.
        /// </summary>
        /// <param name="width">The amount to expand the rectangle's width</param>
        /// <param name="height">The amount to expand the rectangle's height</param>
        public void Expand(float width, float height)
        {
            _left = _left - (width / 2);
            _width = _width + width;

            _top = _top - (height / 2);
            _height = _height + height;
        }
        #endregion



        // Object overrides
        // ================
        #region Object overrides
        /// <summary>
        /// Returns a hash code for this rectangle.
        /// </summary>
        /// <returns>The hash code</returns>
        public override int GetHashCode()
        {
            return (int) ( ((((uint)_left) ^ (((uint)_top) << 13 | ((uint)_top) >> 19)) ^ (((uint)_width) << 26 | ((uint)_width) >> 6)) ^ (((uint)_height) << 7 | ((uint)_height) >> 25) );
        }

        /// <summary>
        /// Returns the string representation of this Rectangle.
        /// </summary>
        /// <returns>The string representation</returns>
        public override string ToString()
        {
            return String.Format("[{0} {1} {2} {3}]", _left, _top, _width, _height);
        }

        /// <summary>
        /// Indicates if the two Rectangle instances are equal.
        /// </summary>
        /// <param name="left">The one Rectangle</param>
        /// <param name="right">The other Rectangle</param>
        /// <returns>A boolean that indicates if the instances are not equal (true) or equal (false).</returns>
        public static bool operator !=(Rectangle left, Rectangle right)
        {
            return
                left.Left != right.Left ||
                left.Top != right.Top ||
                left.Width != right.Width ||
                left.Height != right.Height;
        }

        /// <summary>
        /// Indicates if the two Rectangle instances are equal.
        /// </summary>
        /// <param name="left">The one Rectangle</param>
        /// <param name="right">The other Rectangle</param>
        /// <returns>A boolean that indicates if the instances are equal (true) or not.</returns>
        public static bool operator ==(Rectangle left, Rectangle right)
        {
            return
                left.Left == right.Left &&
                left.Top == right.Top &&
                left.Width == right.Width &&
                left.Height == right.Height;
        }

        /// <summary>
        /// Indicates if the supplied instance is equal to the current instance.
        /// Two Rectangle instances are considered equal if their Left and Top coordinates and their widths
        /// and heights are all equal.
        /// </summary>
        /// <param name="obj">The instance to compare against.</param>
        /// <returns>A boolean that indicates if the two instances are equal.</returns>
        public override bool Equals(object obj)
        {
            if (obj is Rectangle)
                return this == (Rectangle)obj;
            else
                return false;
        }
        #endregion



        // Public constructor
        // ==================
        #region Public constructor
        /// <summary>
        /// Constructs a new Rectangle instance.
        /// </summary>
        /// <param name="left">The rectangle's left coordinate.</param>
        /// <param name="top">The rectangle's top coordinate.</param>
        /// <param name="width">The rectangle's width.</param>
        /// <param name="height">The rectangle's height.</param>
        public Rectangle(float left, float top, float width, float height)
        {
            _left = left;
            _top = top;
            _width = width;
            _height = height;
        }

        #endregion

    } // Rectangle class
}
